import requests
import traceback
from log import info, warn, debug, error

class Singleton(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls,"_instance"):
            cls._instance = super(Singleton, cls).__new__(cls)
        return cls._instance

def byteify(data, ignore_dicts = False):
    """
    json loads function object hook, used to encode string to a dict
    object without utf8 format
    :param data:
    :param ignore_dicts:
    :return:
    """
    # if this is a unicode string, return its string representation
    if isinstance(data, unicode):
        return data.encode('utf-8')
    # if this is a list of values, return list of byteified values
    if isinstance(data, list):
        return [ byteify(item, ignore_dicts=True) for item in data ]
    # if this is a dictionary, return dictionary of byteified keys and values
    # but only if we haven't already byteified it
    if isinstance(data, dict) and not ignore_dicts:
        return {
            byteify(key, ignore_dicts=True): byteify(value, ignore_dicts=True)
            for key, value in data.iteritems()
        }
    # if it's anything else, return it in its original form
    return data

class RestClient:

    def __init__(self, host='localhost', port=2379, protocol='http', timeout=60):
        """

        :param host:
        :param port:
        :param protocol:
        :param timeout:
        """
        self.timeout = timeout
        self.uri = "%s://%s:%d" % (protocol, host, port)

    def get(self, url, params=None, **kwargs):
        ret = ''
        a_url = '%s%s' % (self.uri, url)
        try:
            if "timeout" not in kwargs:
                kwargs["timeout"] = self.timeout
            elif kwargs["timeout"] < 0:
                del kwargs["timeout"]

            res = requests.get(a_url, params, **kwargs)
            if res.status_code == 200:
                ret = res.text
            else:
                error("Failed to get data with status %d." % (res.status_code))
        except Exception as ex:
            error(traceback.format_exc())
            error(ex)
        return ret

    def put(self, url, data=None, **kwargs):
        ret = ''
        a_url = '%s%s' % (self.uri, url)
        try:
            kwargs["timeout"] = self.timeout
            res = requests.put(a_url, data, **kwargs)
            if res.status_code == 201 or res.status_code == 200:
                debug(res.text)
                ret = res.text
            else:
                error("Failed to put data with status %d." % (res.status_code))
        except Exception as ex:
            error(traceback.format_exc())
            error(ex)
        return ret

    def delete(self, url, **kwargs):
        ret = ''
        a_url = '%s%s' % (self.uri, url)
        try:
            kwargs["timeout"] = self.timeout
            res = requests.delete(a_url, **kwargs)
            if res.status_code == 200:
                debug(res.text)
                ret = res.text
            else:
                error("Failed to put data with status %d." % (res.status_code))
        except Exception as ex:
            error(traceback.format_exc())
            error(ex)
        return ret
